package org.micode.common.utils;

import lombok.extern.slf4j.Slf4j;
import org.micode.common.codec.SnowflakeCodec;
import org.micode.common.exception.DataException;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.LineNumberReader;
import java.io.PrintWriter;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Slf4j
public class FileExtUtils {

    public final static String POINT = ".";

    public static long getLineNumber(String filename) {
        if (existFile(filename)) {
            try (FileReader fileReader = new FileReader(new File(filename))) {
                LineNumberReader lineNumberReader = new LineNumberReader(fileReader);
                try {
                    lineNumberReader.skip(Long.MAX_VALUE);
                    long lines = lineNumberReader.getLineNumber() + 1;
                    return lines;
                } finally {
                    lineNumberReader.close();
                }
            } catch (Exception e) {
                throw new DataException("读文件的行数失败！");
            }
        }
        return 0L;
    }

    public static String fullFilename(String dir, String filename) {
        if (StringExtUtils.isAnyEmpty(dir)) {
            return filename;
        } else {
            String path = dir.trim();
            if (path.endsWith("/")) {
                return path + filename;
            } else {
                return path + "/" + filename;
            }
        }
    }

    public static String correctPath(String theDir) {
        if (StringExtUtils.isAnyEmpty(theDir)) {
            return "";
        } else {
            String path = theDir.trim();
            if (path.endsWith("/")) {
                return path.substring(0, path.length() - 1);
            } else {
                return path;
            }
        }
    }

    public static long getFileSize(String filePath) {
        File file = new File(filePath);
        if (file.exists() && file.isFile()) {
            return file.length();
        } else {
            return 0L;
        }
    }

    public static boolean existDir(String dir) {
        File file = new File(dir);
        return file.exists() && file.isDirectory();
    }

    public static boolean existFile(String filePath) {
        File file = new File(filePath);
        return file.exists() && file.isFile();
    }

    public static boolean deleteFile(String filePath) {
        File file = new File(filePath);
        if (file.exists() && file.isFile()) {
            try {
                Files.delete(file.toPath());
            } catch (IOException e) {
                return false;
            }
        }
        return true;
    }

    public static boolean moveFile(String sourceFilename, String targetFilename) {
        File targetFile = new File(targetFilename);
        if (targetFile.exists() && targetFile.isFile()) {
            return true;
        } else {
            try {
                File sourceFile = new File(sourceFilename);
                if (sourceFile.exists() && sourceFile.isFile()) {
                    Files.move(sourceFile.toPath(), targetFile.toPath());
                }
            } catch (IOException e) {
                return false;
            }
        }
        return true;
    }

    public static boolean copyFile(String sourceFilename, String targetFilename) {
        log.debug("Copy file:  \n source: {} \n target: {}", sourceFilename, targetFilename);

        File targetFile = new File(targetFilename);
        if (targetFile.exists() && targetFile.isFile()) {
            return true;
        } else {
            try {
                File sourceFile = new File(sourceFilename);
                if (sourceFile.exists() && sourceFile.isFile()) {
                    // 创建目录(必须先创建目标文件的目录，再进行拷贝)
                    new File(targetFile.getParent()).mkdirs();
                    // 拷贝文件
                    Files.copy(sourceFile.toPath(), targetFile.toPath());
                } else {
                    log.warn("The source file not found: {}", sourceFile);
                    return false;
                }
            } catch (IOException e) {
                log.warn("Copy file failed", e);
                return false;
            }
        }
        return true;
    }

    public static List<String> getChildDirs(String path) {
        List<String> ret = new ArrayList<>();

        File parent = new File(path);
        if (parent.isDirectory()) {
            File[] files = parent.listFiles();
            if (null != files) {
                for (File file : files) {
                    if (file.isDirectory()) {
                        ret.add(file.getName());
                    }
                }
            }
        }
        return ret;
    }

    /**
     * 获取路径下的所有子项
     *
     * @param path 路径
     * @return Map<名称, 是否文件夹>
     */
    public static Map<String, Boolean> getAllChild(String path) {
        Map<String, Boolean> ret = new HashMap<>();

        File parent = new File(path);
        if (parent.isDirectory()) {
            File[] files = parent.listFiles();
            if (null != files) {
                for (File file : files) {
                    ret.put(file.getName(), file.isDirectory());
                }
            }
        }
        return ret;
    }

    public static List<String> getDirFiles(String path) {
        List<String> ret = new ArrayList<>();

        File parent = new File(path);
        if (parent.isDirectory()) {
            File[] files = parent.listFiles();
            if (null != files) {
                for (File file : files) {
                    if (!file.isDirectory()) {
                        ret.add(file.getName());
                    }
                }
            }
        }
        return ret;
    }

    public static String subDirPath(String parentPath, String subDirName) {
        return correctPath(correctPath(parentPath) + "/" + subDirName);
    }

    public static String readExtName(String fileName) {
        if (null == fileName) {
            return "";
        }
        int pos = fileName.lastIndexOf(POINT);
        if (pos >= 0) {
            return fileName.substring(pos + 1);
        }
        return "";
    }

    /**
     * 文件类型验证
     * @param filename 文件名
     * @param typeName 类型名
     * @return 是否指定类型的文件
     */
    public static boolean validFileType(String filename, String typeName) {
        if (null == typeName || null == filename) {
            return false;
        }

        String ext = readExtName(filename);
        if (StringExtUtils.isAnyEmpty(ext)) {
            return false;
        }

        return ext.toLowerCase().equals(typeName.toLowerCase());
    }

    public static boolean buildDir(String dir) {
        File path = new File(dir);
        return path.mkdirs();
    }

    public static void insertLinesToFileTop(String fullFilename, List<String> linesWantInserted) throws IOException {
        File inFile = new File(fullFilename);
        File outFile = new File("/tmp/sql" + SnowflakeCodec.defaultNextId() + ".tmp");

        try (FileInputStream fis = new FileInputStream(inFile)) {
            try (BufferedReader in = new BufferedReader(new InputStreamReader(fis))) {
                // 输出
                try (FileOutputStream fos = new FileOutputStream(outFile)) {
                    try (PrintWriter out = new PrintWriter(fos)) {
                        linesWantInserted.forEach(out::println);
                        String thisLine;
                        while ((thisLine = in.readLine()) != null) {
                            // 输出读取到的数据
                            out.println(thisLine);
                        }
                        out.flush();
                    }
                }
            }
        }

        try {
            if (inFile.delete()) {
                log.debug("文件更名处理：{} =》 {}", outFile.getAbsolutePath(), inFile.getAbsolutePath());
                if (!moveFile(outFile.getAbsolutePath(), inFile.getAbsolutePath())) {
                    log.warn("文件更名失败！{}", outFile.getAbsolutePath());
                }
//            outFile.renameTo(inFile);
            } else {
                log.warn("文件删除失败！({})", inFile.getAbsolutePath());
            }
        } catch (Exception e) {
            log.error("文件删除或更名异常: ", e);
            throw new DataException("文件删除或更名异常: " + e.getMessage());
        }
    }

    public static boolean copyFileDelPre(String sourceFilename, String targetFilename, String preTemplate) {
        log.debug("Copy file ({}):  \n source: {} \n target: {}", preTemplate, sourceFilename, targetFilename);

        File targetFile = new File(targetFilename);
        if (targetFile.exists() && targetFile.isFile()) {
            return true;
        } else {
            try {
                File sourceFile = new File(sourceFilename);
                if (sourceFile.exists() && sourceFile.isFile()) {
                    // 创建目录(必须先创建目标文件的目录，再进行拷贝)
                    new File(targetFile.getParent()).mkdirs();

                    long pl = 0;

                    try (FileInputStream fis = new FileInputStream(sourceFile)) {
                        try (BufferedReader in = new BufferedReader(new InputStreamReader(fis))) {
                            // 输出
                            try (FileOutputStream fos = new FileOutputStream(targetFile)) {
                                try (PrintWriter out = new PrintWriter(fos)) {
                                    String thisLine;
                                    while ((thisLine = in.readLine()) != null) {
                                        if (pl < 3) {
                                            System.out.println(thisLine);
                                        }
                                        // 输出读取到的数据
                                        int pos = thisLine.indexOf(preTemplate);
                                        if (pos >= 0) {
                                            thisLine = thisLine.substring(pos + preTemplate.length()).trim();
                                        }
                                        out.println(thisLine);
                                        pl = pl + 1;
//                                        if (pl % 1000000 == 0) {
//                                            System.out.println(pl);
//                                        }
                                    }
                                    out.flush();
                                }
                            }
                        }
                        System.out.println("处理了：" + pl);
                    }
                } else {
                    log.warn("The source file not found: {}", sourceFile);
                    return false;
                }
            } catch (IOException e) {
                log.warn("Copy file failed", e);
                return false;
            }
        }
        return true;
    }

    public static void main(String[] args) {
        File directory = new File("G:/0615/wuguan_jsonmsg.log");//参数为空
        String courseFile = null;
        courseFile = directory.getPath();
        System.out.println(courseFile);

//        for (int i = 1; i < 52; i++) {
//            String sourceFile = "G:/0615/wuguan_jsonmsg.log." + i;
//            String destFile = "D:/temp/0615/wuguan_" + i + ".log";
//            copyFileDelPre(sourceFile, destFile, " - [ INFO ] ");
//        }
    }

}
